package com.example.base.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Xiongx
 * @version 1.0
 * @date 2021/6/25 15:02
 * @since JDK 1.8
 */
public class ReflectUtils {

    public static Class<?> getClass(String clazz){
        try {
            return Class.forName(clazz);
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static boolean existsClazz(String clazz)  {
        try {
            Class.forName(clazz);
            return true;
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static Object methodInvoke(Object obj,String methodName,Object...args){
        Method method=getMethodByName(obj.getClass(),methodName);
        if(method==null){
            return null;
        }
        Object val=null;
        try {
            if(args==null || args.length == 0){
                val=method.invoke(obj);
            }else {
                val=method.invoke(obj,args);
            }
            return val;
        }catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return val;
    }

    /**
     * 方法调用
     * @return
     */
    public static Object methodInvoke(String clazz,String methodName,Object...args){
        Method method1=getMethodByName(clazz,methodName);
        if(method1==null){
            return null;
        }
        Object obj=getObjectByClass(clazz);
        Object value=null;
        try {
            if(args==null || args.length<=0){
                value=method1.invoke(obj);
            }else {
                value=method1.invoke(obj,args);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return value;
    }




    /**
     *
     * @param clazz 类路径
     * @param name 方法名称
     * @param <T> 方法
     * @return
     */
    public static <T> Method getMethodByName(String clazz,String name){
        try {
            Class<T> cls=(Class<T>) Class.forName(clazz);
            return getMethodByName(cls,name);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    /**
     *
     * @param cls 反射
     * @param name 方法名
     * @param <T>
     * @return
     */
    public static <T> Method getMethodByName(Class<T> cls,String name){
        Method[] methods=cls.getDeclaredMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method=methods[i];
            if(!method.getName().equals(name)){
                continue;
            }
            return method;
        }
        return null;
    }




    /**
     * 获取该对象的属性值
     * @param obj
     * @param feild
     * @return
     */
    public static Object getObjectByFeild(Object obj,String feild){
        Field field=getFieldByName(feild,obj.getClass());
        field.setAccessible(true);
        try {
            return field.get(obj);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更改数据对象的值
     * @param obj  对象
     * @param feild 该对象的属性
     * @param value  要更改的值
     */
    public static void setObjectData(Object obj,String feild,Object value){
        Field field=getFieldByName(feild,obj.getClass());
        field.setAccessible(true);
        try {
            field.set(obj,value);
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 私有获取单独某个属性
     * @param name
     * @param cls
     * @return
     */
    private static Field getFieldByName(String name,Class cls){
        Field[] fields=getFieldArray(cls);
        for (int i = 0; i < fields.length ; i++) {
            Field fields1=fields[i];
            if(!fields1.getName().equals(name)){
                continue;
            }
            return fields1;
        }
        return null;
    }

    /**
     * 获取属性列表
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> Field[] getFieldArray(String cls){
        try {
            Class clazz=Class.forName(cls);
            Class<T> tClass=(Class<T>)clazz;
            return getFieldArray(tClass);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取属性列表
     * @param cls 反射
     * @param <T>
     * @return 属性列表
     */
    public static <T> Field[] getFieldArray(Class<T> cls){
        return cls.getDeclaredFields();
    }


    /**
     * 通过字符串获取对象
     * @param clazz
     * @param
     * @return
     */
    public static Object getObjectByClass(String clazz){
        try {
            Class cls=Class.forName(clazz);
            return getObjectByClass(cls);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 通过反射获取对象
     * @param <T>
     * @return
     */
    public static  <T> T getObjectByClass(Class<T> cls){
        try {
            return cls.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
